
#ifndef _LOGUTIL_H_
#define _LOGUTIL_H_

#include "common.h"

#include <iostream>
#include <sstream>

/**
 * This is a simple logging utility that allows level based logging.  
 * Important features are type safety, portability and flexibility.
 * The output stream and global level are defined at compile time
 * (see the LOGUTIL_LOG_STREAM and LOGUTIL_LOG_LEVEL preprocessor
 * variables).
 *
 * This code is based on the article by Petru Marginean,
 * available here: http://www.ddj.com/cpp/201804215
 */

// Define global output stream
#ifndef LOGUTIL_STREAM
 #define LOGUTIL_STREAM std::cerr
#endif

// Define global logging level
#ifndef LOGUTIL_LEVEL
 #define LOGUTIL_LEVEL LEVEL_DEBUG
#endif

#define LOG(level) \
 if (level < LogUtil::Level()) ; \
 else LogUtil().Get(level)

#define DEBUG   LOG(LEVEL_DEBUG)
#define INFO    LOG(LEVEL_INFO)
#define WARN    LOG(LEVEL_WARN)
#define ERROR   LOG(LEVEL_ERROR)
#define FATAL   LOG(LEVEL_FATAL)

__BEGIN_NAMESPACE_DECL_

enum LogLevel {
    LEVEL_DEBUG, 
    LEVEL_INFO, 
    LEVEL_WARN, 
    LEVEL_ERROR, 
    LEVEL_FATAL
};

class LogUtil
{
    public:
        LogUtil();
        ~LogUtil();
        std::ostringstream& Get(LogLevel level);
        static LogLevel Level();
        static void SetLevel(LogLevel level);
    
    protected:
        static LogLevel level_;
        std::ostringstream os_;
        bool exitFlag;

    private:
        LogUtil(const LogUtil&);
        LogUtil& operator =(const LogUtil&);
};

__END_NAMESPACE_DECL_

#endif

